﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;

namespace NiuX.AspNetCore.DynamicWebApi
{
    public static class DynamicWebApiServiceExtensions
    {
        public static IServiceCollection AddDynamicWebApi(this IServiceCollection services)
        {
            return AddDynamicWebApi(services, new DynamicWebApiOptions());
        }

        public static IServiceCollection AddDynamicWebApi(this IServiceCollection services, Action<DynamicWebApiOptions> optionsAction)
        {
            var options = new DynamicWebApiOptions();

            optionsAction?.Invoke(options);

            return AddDynamicWebApi(services, options);
        }

        private static IServiceCollection AddDynamicWebApi(this IServiceCollection services, DynamicWebApiOptions options)
        {
            if (options == null)
            {
                throw new ArgumentException(nameof(options));
            }

            options.Valid();

            DynamicWebApiConsts.DefaultAreaName = options.DefaultAreaName;
            DynamicWebApiConsts.DefaultHttpVerb = options.DefaultHttpVerb;
            DynamicWebApiConsts.DefaultApiPreFix = options.DefaultApiPrefix;
            DynamicWebApiConsts.ControllerSuffixes = options.RemoveControllerSuffixes;
            DynamicWebApiConsts.ActionSuffixes = options.RemoveActionSuffixes;
            DynamicWebApiConsts.FormBodyBindingIgnoredTypes = options.FormBodyBindingIgnoredTypes;
            DynamicWebApiConsts.GetRestFulActionName = options.GetRestFulActionName;
            DynamicWebApiConsts.AssemblyAutoApiOptions = options.AssemblyAutoApiOptions;

            var partManager = services.GetSingletonInstanceOrNull<ApplicationPartManager>();
            if (partManager == null)
            {
                throw new InvalidOperationException("\"AddAutoApi\" must be after \"AddMvc\".");
            }

            partManager.FeatureProviders.Add(new DynamicWebApiControllerFeatureProvider());

            services.Configure<MvcOptions>(options =>
            {
                options.Conventions.Add(new DynamicWebApiConvention());
            });

            return services;
        }

        private static T GetSingletonInstanceOrNull<T>(this IServiceCollection services)
        {
            return (T)services.FirstOrDefault(d => d.ServiceType == typeof(T))?.ImplementationInstance;
        }
    }
}
